package org.xuan.poi.plus.word;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;
import org.xuan.poi.plus.word.io.IOUtils;
import org.xuan.poi.plus.word.obj.CustomXWPFDocument;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/***
 * 操作word段落
 */
public class WordParagraphsUtils {

    /**
     * 替换所有段落中的标记
     *
     * @param xwpfParagraphList
     * @param params
     */
    public static void replaceInAllParagraphs(List<XWPFParagraph> xwpfParagraphList, Map<String, Object> params) throws Exception {
        for (XWPFParagraph paragraph : xwpfParagraphList) {
            if (paragraph.getText() == null || paragraph.getText().equals("")) continue;
            for (String key : params.keySet()) {
                if (paragraph.getText().contains(key)) {
                    replaceInParagraph(paragraph, key, params.get(key));
                }
            }
        }
    }

    /**
     * 替换段落中的字符串
     *
     * @param xwpfParagraph
     * @param oldString
     * @param newObj
     */
    public static void replaceInParagraph(XWPFParagraph xwpfParagraph, String oldString, Object newObj) throws Exception {
        Map<String, Integer> pos_map = findSubRunPosInParagraph(xwpfParagraph, oldString);
        if (pos_map != null) {
            System.out.println("start_pos:" + pos_map.get("start_pos"));
            System.out.println("end_pos:" + pos_map.get("end_pos"));

            List<XWPFRun> runs = xwpfParagraph.getRuns();
            XWPFRun modelRun = runs.get(pos_map.get("end_pos"));
            XWPFRun xwpfRun = xwpfParagraph.insertNewRun(pos_map.get("end_pos") + 1);

            if(newObj instanceof Map){
                CustomXWPFDocument doc = (CustomXWPFDocument) xwpfRun.getDocument();
                Map pic = (Map) newObj;
                int width = Integer.parseInt(pic.get("width").toString());
                int height = Integer.parseInt(pic.get("height").toString());
                int picType = getPictureType(pic.get("type").toString());
                //获取图片流，因本人项目中适用流
                String byteArray = (String) pic.get("content");
                CTInline inline = xwpfRun.getCTR().addNewDrawing().addNewInline();
                insertPicture(doc, byteArray, inline, width, height, picType);

                xwpfRun.setText("");
            }else{
                System.out.println("字体大小：" + modelRun.getFontSize());
                if (modelRun.getFontSize() != -1) xwpfRun.setFontSize(modelRun.getFontSize());//默认值是五号字体，但五号字体getFontSize()时，返回-1
                System.out.println("字体：" + modelRun.getFontFamily());
                String fontFamily = modelRun.getFontFamily();

                if(isChinise(fontFamily)){
                    // 新建 字体配置对象
                    CTFonts font = xwpfRun.getCTR().addNewRPr().addNewRFonts();
                    //中文
                    font.setEastAsia(fontFamily);
                }else{
                    xwpfRun.setFontFamily(modelRun.getFontFamily());
                }
                xwpfRun.setUnderline(modelRun.getUnderline());
                xwpfRun.setText(newObj == null ? "" : newObj.toString());
            }
            for (int i = pos_map.get("end_pos"); i >= pos_map.get("start_pos"); i--) {
                System.out.println("remove run pos in :" + i);
                xwpfParagraph.removeRun(i);
            }
        }
    }



    /**
     * 找到段落中子串的起始XWPFRun下标和终止XWPFRun的下标
     *
     * @param xwpfParagraph
     * @param substring
     * @return
     */
    public static Map<String, Integer> findSubRunPosInParagraph(XWPFParagraph xwpfParagraph, String substring) {

        List<XWPFRun> runs = xwpfParagraph.getRuns();
        int start_pos = 0;
        int end_pos = 0;
        String subtemp = "";
        for (int i = 0; i < runs.size(); i++) {
            subtemp = "";
            start_pos = i;
            for (int j = i; j < runs.size(); j++) {
                if (runs.get(j).getText(runs.get(j).getTextPosition()) == null) continue;
                subtemp += runs.get(j).getText(runs.get(j).getTextPosition());
                if (subtemp.equals(substring)) {
                    end_pos = j;
                    Map<String, Integer> map = new HashMap<String, Integer>();
                    map.put("start_pos", start_pos);
                    map.put("end_pos", end_pos);
                    return map;
                }
            }
        }
        return null;
    }

    /***
     * 判断字符串是否包含中文
     * @param fontFamily
     * @return
     */
    private static boolean isChinise(String fontFamily) {
        if(StringUtils.isBlank(fontFamily)){
            return false;
        }else{
            char[] chars = fontFamily.toCharArray();
            for (char c:chars
            ) {
                boolean chinese = isChinese(c);
                if(chinese)
                    return chinese;
            }
            return false;
        }
    }

    /**
     * 判断是否为中文字符
     * @param c
     * @return
     */
    public static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
            return true;
        }
        return false;
    }

    /**
     * 获取图片对应类型代码
     *
     * @param picType
     * @return int
     */
    private static int getPictureType(String picType) {
//        logger.info("WordUtils.getPictureType");
        int res = CustomXWPFDocument.PICTURE_TYPE_PICT;
        if (picType != null) {
            if (picType.equalsIgnoreCase("png")) {
                res = CustomXWPFDocument.PICTURE_TYPE_PNG;
            } else if (picType.equalsIgnoreCase("dib")) {
                res = CustomXWPFDocument.PICTURE_TYPE_DIB;
            } else if (picType.equalsIgnoreCase("emf")) {
                res = CustomXWPFDocument.PICTURE_TYPE_EMF;
            } else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {
                res = CustomXWPFDocument.PICTURE_TYPE_JPEG;
            } else if (picType.equalsIgnoreCase("wmf")) {
                res = CustomXWPFDocument.PICTURE_TYPE_WMF;
            }
        }
        return res;
    }

    /**
     * insert Picture
     *
     * @param document
     * @param filePath
     * @param inline
     * @param width
     * @param height
     * @throws InvalidFormatException
     * @throws FileNotFoundException
     */
    private static void insertPicture(/*XWPFDocument*/CustomXWPFDocument document, String filePath,
                                                      CTInline inline, int width,
                                                      int height, int imgType) throws Exception {
//        logger.info("WordUtils.insertPicture");
        //通过流获取图片，因本人项目中，是通过流获取
        //document.addPictureData(imgFile,imgType);
        HttpURLConnection conn = null;
        InputStream inStream = null;
        try {
//            logger.info("WordUtils.insertPicture,filePath="+filePath);
            byte[] bytes = IOUtils.getByteGET(filePath);

            document.addPictureData(bytes,imgType);
            int id = document.getAllPictures().size() - 1;
            final int EMU = 9525;
            width *= EMU;
            height *= EMU;
            String blipId =
                    document.getAllPictures().get(id).getPackageRelationship().getId();
            String picXml = getPicXml(blipId, width, height);
            XmlToken xmlToken = null;
            xmlToken = XmlToken.Factory.parse(picXml);
            inline.set(xmlToken);
            inline.setDistT(0);
            inline.setDistB(0);
            inline.setDistL(0);
            inline.setDistR(0);
            CTPositiveSize2D extent = inline.addNewExtent();
            extent.setCx(width);
            extent.setCy(height);
            CTNonVisualDrawingProps docPr = inline.addNewDocPr();
            docPr.setId(id);
            docPr.setName("IMG_" + id);
            docPr.setDescr("IMG_" + id);
        } catch (Exception e) {
//            logger.error("WordUtils.insertPicture", e);
            throw e;
        }finally {
            if(inStream != null){
                inStream.close();
            }
            if(conn != null){
                conn.disconnect();
            }
        }
    }
    /**
     * get the xml of the picture
     *
     * @param blipId
     * @param width
     * @param height
     * @return
     */
    private static String getPicXml(String blipId, int width, int height) {
        String picXml =
                "" + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
                        "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                        "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                        "         <pic:nvPicPr>" + "            <pic:cNvPr id=\"" + 0 +
                        "\" name=\"Generated\"/>" + "            <pic:cNvPicPr/>" +
                        "         </pic:nvPicPr>" + "         <pic:blipFill>" +
                        "            <a:blip r:embed=\"" + blipId +
                        "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
                        "            <a:stretch>" + "               <a:fillRect/>" +
                        "            </a:stretch>" + "         </pic:blipFill>" +
                        "         <pic:spPr>" + "            <a:xfrm>" +
                        "               <a:off x=\"0\" y=\"0\"/>" +
                        "               <a:ext cx=\"" + width + "\" cy=\"" + height +
                        "\"/>" + "            </a:xfrm>" +
                        "            <a:prstGeom prst=\"rect\">" +
                        "               <a:avLst/>" + "            </a:prstGeom>" +
                        "         </pic:spPr>" + "      </pic:pic>" +
                        "   </a:graphicData>" + "</a:graphic>";
        return picXml;
    }
}
